home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 34.zip / BS1 part 34 / FredFish PD 317.adf / Uniq / uniq.c < prev   
C/C++ Source or Header  |  1990-02-06  |  8KB  |  472 lines

  1. /************************************************************************ 
  2. *                                                                       * 
  3. *                                                                       * 
  4. *                      Filename:        uniq.c                          *      
  5. *                                    *
  6. *  uniq - compact repeated lines        Author: John Woods      *
  7. *                                    *
  8. *      ( looks like UNIX version )                    *
  9. *                                    *
  10. * Written 02/08/86 by John Woods, placed into public domain.  Enjoy.    *
  11. *                                    *
  12. * Amiga port by Gary Duncan , Canberra Australia                        * 
  13. *                                                                       * 
  14. *                                                                       * 
  15. *-----------------------------------------------------------------------* 
  16. *
  17. *
  18. * Modification record: 
  19. *~~~~~~~~~~~~~~~~~~~~
  20. * Date         By whom             Change 
  21. * ----         -------             ------ 
  22. *        JW           Original 
  23. * 04Jan90     GMD           Amiga port : reformatted, headers 
  24. *                         added , usage() added.    
  25. *                        +/-n option bug fixed
  26. *
  27. * Function    Description
  28. * ~~~~~~~~    ~~~~~~~~~~~ 
  29. *+ main  
  30. *+ skip 
  31. *+ equal
  32. *+ show
  33. *+ uniq  
  34. *+ usage
  35. *+ getline
  36. *+ xfopen 
  37. *+  
  38. *
  39. *
  40. *******************************************************************************/
  41.  
  42. #include "stdio.h"
  43. #include "ctype.h"
  44.  
  45. /*
  46.  *    give a version # ( GMD )
  47.  */
  48. #define    VERS    "1.1"
  49.  
  50. /* If the symbol WRITE_ERROR is defined, uniq will exit(1) if it gets a
  51.  * write error on the output.  This is not (of course) how V7 uniq does it,
  52.  * so undefine the symbol if you want to lose your output to a full disk
  53.  */
  54.  
  55. #define WRITE_ERROR 1
  56. #define GBUF 1024 
  57.  
  58. extern char *MakeDate[] ;
  59.  
  60. FILE *fopen();
  61. FILE *xfopen();
  62.  
  63. char xbuffer [BUFSIZ];
  64. int xuflag = 1;            /* default is union of -d and -u outputs */
  65. int xdflag = 1;            /* flags are mutually exclusive */
  66. int xcflag = 0;
  67. int xfields = 0;
  68. int xchars = 0;
  69.  
  70.  
  71. char *xcurline ;
  72. char *xprevline ;
  73. char xbuf1 [GBUF]  ;
  74. char xbuf2 [GBUF]  ;
  75.  
  76. /*************************************************************************** 
  77.  
  78.  
  79.   Name :          main
  80.  
  81.   Purpose:    ..every C prog deserves one..
  82.  
  83.  
  84.   Entry    :           
  85.  
  86.  
  87.   Returns  :           
  88.                                
  89.  
  90.  
  91. ****************************************************************************/ 
  92.  
  93.  
  94. int
  95. main(argc,argv)
  96. char *argv[];
  97. {
  98.   char *p;
  99.   int inf = -1, outf;
  100.  
  101.  
  102.   if (argc == 1 )
  103.   {
  104.     usage() ;
  105.     exit (1) ;
  106.   }    
  107.  
  108.   setbuf(stdout, xbuffer);
  109.   
  110.   for (--argc, ++argv; (argc > 0) && (**argv == '-' || **argv == '+');
  111.        --argc, ++argv) 
  112.   {
  113.       if (**argv == '+')
  114.           xchars = atoi(*argv + 1);
  115.  
  116.       else if (isdigit(argv[0][1]))
  117.           xfields = atoi(*argv + 1);
  118.  
  119.       else if (argv[0][1] == '\0')
  120.           inf = 0;        /* - is stdin */
  121.  
  122.       else
  123.       {
  124.           for (p = *argv+1; *p; p++) {
  125.               switch(*p) {
  126.               case 'd':    
  127.                 xdflag = 1; 
  128.                 xuflag = 0;     
  129.                 break;
  130.               case 'u':    
  131.                 xuflag = 1; 
  132.                 xdflag = 0; 
  133.                 break;
  134.               case 'c':    
  135.                 xcflag = 1; 
  136.                 break;
  137.               default:    
  138.                 usage();
  139.                 exit(1) ;
  140.           }
  141.          }
  142.       }
  143.   }
  144.   /* input file */
  145.   if (argc == 0)
  146.     inf = 0;
  147.   else
  148.     if (inf == -1) {        /* if - was not given */
  149.         fclose(stdin);
  150.         xfopen(*argv++, "r");
  151.         argc--;
  152.       }
  153.  
  154.   if (argc == 0) 
  155.     outf = 1;
  156.   else {
  157.       fclose(stdout);
  158.      xfopen(*argv++, "w");
  159.      argc--;
  160.   }
  161.  
  162.   uniq();
  163.   fflush(stdout);
  164.   exit(0);
  165. }
  166.  
  167. /*************************************************************************** 
  168.  
  169.  
  170.   Name :          skip
  171.  
  172.   Purpose:
  173.         +- n options ; skip fields / charas in fields
  174.  
  175.   Entry    :           
  176.  
  177.  
  178.   Returns  :           
  179.         ptr to (+nth) chara  in (-nth)field
  180.         or NULL if not found                                
  181.  
  182.  
  183. ****************************************************************************/ 
  184.  
  185.  
  186.  
  187. char *skip(s)
  188.  
  189. char *s;
  190. {
  191. int n;
  192.   
  193.   /* skip xfields */
  194.  
  195.   for (n = xfields; n > 0 ; --n) 
  196.   {
  197.                             /* skip blanks */
  198.     while (*s && (*s == ' ' || *s == '\t')) 
  199.         s++;
  200.  
  201.     if (!*s)
  202.          return s;
  203.  
  204.     while (*s && (*s != ' ' && *s != '\t')) 
  205.         s++;
  206.  
  207.     if (!*s) 
  208.         return s;
  209.   }
  210.   /* skip characters */
  211.   
  212.   for (n = xchars; n > 0; --n) {
  213.     if (!*s) 
  214.         return s;
  215.     s++;
  216.   }
  217.   return s;
  218. }
  219.  
  220. /*************************************************************************** 
  221.  
  222.  
  223.   Name :          equal
  224.  
  225.   Purpose:
  226.         tests 2 strings for equality
  227.  
  228.   Entry    :           
  229.  
  230.  
  231.   Returns  :           
  232.                                
  233.  
  234.  
  235. ****************************************************************************/ 
  236.  
  237.  
  238.  
  239. int equal(s1, s2) 
  240.  
  241. char *s1, *s2;
  242. {
  243.   return !strcmp( skip(s1), skip(s2));
  244. }
  245.  
  246. /*************************************************************************** 
  247.  
  248.  
  249.   Name :          show
  250.  
  251.   Purpose:
  252.  
  253.  
  254.   Entry    :           
  255.  
  256.  
  257.   Returns  :           
  258.                                
  259.  
  260.  
  261. ****************************************************************************/ 
  262.  
  263.  
  264.  
  265. void
  266. show(line,count) 
  267.  
  268. int  count ;
  269. char *line; 
  270. {
  271.   if (xcflag) 
  272.     printf("%4d %s", count,line);
  273.   else {
  274.     if ((xuflag && count == 1) || (xdflag && count != 1))
  275.         printf("%s", line);
  276.   }
  277. }
  278.  
  279. /*************************************************************************** 
  280.  
  281.  
  282.   Name :          uniq
  283.  
  284.   Purpose:
  285.  
  286.  
  287.   Entry    :           
  288.  
  289.  
  290.   Returns  :           
  291.                                
  292.  
  293.  
  294. ****************************************************************************/ 
  295.  
  296.  
  297.  
  298.  
  299. int
  300. uniq()
  301. {
  302.   char *ptr;
  303.   int seen = 1 ;
  304.  
  305.   /* initialise "prev" line ( setup ?? ) */
  306.  
  307.   xprevline = xbuf1;
  308.   if (getline(xprevline, GBUF) < 0) 
  309.     return(0);
  310.  
  311.   xcurline = xbuf2;
  312.  
  313.   /* get xcurline and compare 
  314.    * if not equal, dump xprevline and swap pointers 
  315.    * else continue, bumping seen count
  316.    */
  317.   while (getline(xcurline, GBUF) > 0) {
  318.     if (!equal(xprevline, xcurline)) {
  319.           show(xprevline, seen);
  320.           seen = 1;
  321.           ptr = xcurline;
  322.           xcurline = xprevline;
  323.           xprevline = ptr;
  324.     } 
  325.     else
  326.           seen += 1;
  327.   }
  328.   show(xprevline, seen);
  329.   return 0;
  330. }
  331.  
  332. /*************************************************************************** 
  333.  
  334.  
  335.   Name :          getline
  336.  
  337.   Purpose:
  338.  
  339.  
  340.   Entry    :           
  341.  
  342.  
  343.   Returns  :           
  344.             -1 ; EOF                               
  345.             # of charas read 
  346.  
  347. ****************************************************************************/ 
  348.  
  349.  
  350.  
  351.  
  352. int getline(buf,count)
  353.  
  354. char *buf;
  355. int count;
  356. {
  357. char c;
  358. char * cats = buf ;
  359. int ct = 0;
  360.  
  361.     while (ct++ < count) 
  362.     {
  363.       c = getc(stdin);
  364.       if (c <= 0) 
  365.         return(-1);
  366.       *cats++ = c;
  367.       if (c == '\n') 
  368.         {
  369.        *cats++ = 0;
  370.        /*
  371.         *    read another line if no 'n' compliance
  372.         */
  373.         if ( xchars || xfields )
  374.         {
  375.         if ( *skip(buf) == '\0' )
  376.         {
  377.            ct = 0 ;
  378.            cats = buf ;
  379.         }
  380.         else        /* exit */
  381.            return (ct) ;
  382.         }
  383.         else
  384.         return (ct) ;  
  385.     }
  386.      }
  387.   return(ct);
  388.  
  389. }
  390.   
  391.  
  392. /*************************************************************************** 
  393.  
  394.  
  395.   Name :          xfopen
  396.  
  397.   Purpose:
  398.  
  399.  
  400.   Entry    :           
  401.  
  402.  
  403.   Returns  :           
  404.                                
  405.  
  406.  
  407. v****************************************************************************/ 
  408.  
  409.  
  410.  
  411. FILE *xfopen(fn, mode)
  412.  
  413. char *fn, *mode; 
  414. {
  415.   FILE *p;
  416.   extern int errno;
  417.   extern char *sys_errlist[];
  418.  
  419.   if ((p = fopen(fn,mode))  == NULL) {
  420.       perror("uniq");
  421.     fflush(stdout);
  422.     exit(1);
  423.   }
  424.   return (p);
  425. }
  426.  
  427. /*************************************************************************** 
  428.  
  429.  
  430.   Name :          usage
  431.  
  432.   Purpose:
  433.  
  434.  
  435.   Entry    :           
  436.  
  437.  
  438.   Returns  :           
  439.                                
  440.  
  441.  
  442. ****************************************************************************/ 
  443.  
  444.  
  445. int
  446. usage()
  447.  
  448. {
  449. static char *rats[] = {
  450.   "      - Written by John Woods (Amiga port by Gary Duncan)\n",
  451.   "usage:    uniq [-udc] [+n] [-n] [input [output]]" ,
  452.   "             -c ; print lines , count repeated ones",
  453.   "             -d ; print first occurrence of replicated lines only (default)",
  454.   "             -u ; print only unique lines",
  455.   "             +n ; skip n charas from start of field",
  456.   "             -n ; skip n fields from start of line",
  457.   ""
  458.     } ;
  459.  
  460. int    j = 0 ;
  461. char * ptr  ;
  462.  
  463.  
  464.     fprintf(stderr, "uniq: Version %s [ %s ]\n" , VERS , MakeDate[0] ) ;
  465.     
  466.       while ( *(ptr=rats[j++]) )
  467.           fprintf(stderr,"%s\n" , ptr );
  468. }
  469.